package ru.aptu.gsp_banking.service_impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.aptu.billing.BillingClientFactory;
import ru.aptu.billing_client.BillingClient;
import ru.aptu.billing_message.*;
import ru.aptu.gsp_banking.dao.AccountDAO;
import ru.aptu.gsp_banking.dao.TransactionDAO;
import ru.aptu.gsp_banking.domain.Account;
import ru.aptu.gsp_banking.domain.Payment;
import ru.aptu.gsp_banking.domain.Transaction;
import ru.aptu.gsp_banking.service.CurrencyService;
import ru.aptu.gsp_banking.service.PaymentService;
import ru.aptu.gsp_banking.snmp.Sender;

/**
 * Created by IntelliJ IDEA.
 * User: alex
 * Date: 1/27/12
 * Time: 1:07 PM
 */

@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private TransactionDAO transactionDAO;

    @Autowired
    private AccountDAO accountDAO;

    @Autowired
    private CurrencyService currencyService;

    class NegativeResponseException extends Exception {}

    private void checkMessage(ResponseMessage message) throws NegativeResponseException {
        if (message == null) {
            Sender.sendV2cTrap("Error receiving message");
            throw new NegativeResponseException();
        } else {
            Sender.sendV2cTrap("Receiving message: " + message.getStatus());
            if (!message.getStatus().equals(BasicMessage.Status.OK))
                throw new NegativeResponseException();
        }
    }

    @Transactional
    public boolean submitPayment(Payment payment) {

        Account accountFrom = accountDAO.getAccountById(payment.getAccountId());

        if (accountFrom.getBalance()
                < currencyService.convert(payment.getAmount(), payment.getCurrency(), accountFrom.getCurrency())
                || payment.getAmount() <= 0) {
            return false;
        }

        BillingClient client = BillingClientFactory.createDefaultBillingClient();
        if (!client.initConnection()) {
            Sender.sendV2cTrap("Error connecting to billing server.");
            return false;
        }

        try {
            Sender.sendV2cTrap("Sending check protocol message");
            ResponseMessage message = client.sendMessage(new RequestMessage(BasicMessage.MessageType.CHECK_PROTOCOL));
            checkMessage(message);

            Sender.sendV2cTrap("Sending check account message");
            message = client.sendMessage(new AccountCheckMessage(BasicMessage.ServiceType.MOBILE_PHONE, payment.getPaymentId()));
            checkMessage(message);

            Transaction transaction = new Transaction(
                    payment.getAccountId(), -payment.getAmount(), payment.getCurrency(),
                    "Payment: MOBILE PHONE #" + payment.getPaymentId());

            transactionDAO.saveTransaction(transaction);
            try {
                Sender.sendV2cTrap("Sending payment message");
                message = client.sendMessage(new PaymentRequestMessage(BasicMessage.ServiceType.MOBILE_PHONE,
                        payment.getPaymentId(), transaction.getId(), payment.getAmount(), payment.getCurrency()));
                checkMessage(message);
            } catch (NegativeResponseException e) {
                transactionDAO.deleteTransaction(transaction);
                throw e;
            }

        } catch (NegativeResponseException e) {
            return false;
        } finally {
            client.close();
        }
        return true;
    }
}
